using Com.FirstSolver.Splash;
using Furion;
using Furion.ClayObject;
using Furion.Logging;
using HanwangService.service;
using Lxb.Model;
using Lxb.Model.Service;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Mina.Core.Session;
using Mina.Filter.Codec;
using Mina.Transport.Socket;
using MqttModel;
using Newtonsoft.Json;
using SqlSugar;
using StackExchange.Redis;
using System.Net;
using System.Text.Json.Serialization;

namespace HanwangService
{
    public class Worker : BackgroundService
    {

        /// <summary>
        /// 用于密钥交换的服务器端证书
        /// </summary>
        private SM2UserInformation SM2ServerInfo = new SM2UserInformation(
            "Com.FirstSolver.Splash",
            "DE078F1052116A4F706288AB9EC8E10009EAA510B68B68D917AA63F3D07B3876",
            "59C9ADD36106ABD5D26CCF7F92D8BBAD33A0C55D0CF9F644CF97D340EDDFB949",
            "D781D3BBD4F1B8263DBF68613CF7E830BBD6CC569740303D4DDEAEB5216AE639"
            );
        /// <summary>
        /// 服务器是否已运行
        /// </summary>
        private bool IsServerRunning = false;

        /// <summary>
        /// 侦听服务器
        /// </summary>
        private AsyncSocketAcceptor TcpServer ;
        private string IP = "0.0.0.0";
        private readonly ILogger<Worker> _logger;
        private readonly int port = 9910;
        private readonly bool isEncryption = false;
        private readonly string? topath;
        private readonly string? frompath;

        public Worker(ILogger<Worker> logger)
        {
            _logger = logger;
            Starservice();
            topath = App.Configuration["facepath"];// @"E:\weixin\FaceImage\";
            frompath = App.Configuration["fromfacepath"];// @"E:\weixin\FaceImage\";

        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                if (_logger.IsEnabled(LogLevel.Information))
                {
                    //_logger.LogInformation("TCP Worker running at: {time}", DateTimeOffset.Now);
                }
                await Task.Delay(1000, stoppingToken);
            }
        }

        private long lasttime = DateTime.Now.Ticks;
        //返回已经过去的时间毫秒 
        private bool TimeOut(int tlong = 2000)
        {
            long now = DateTime.Now.Ticks;
            long time = now - lasttime;
            if (time > tlong)
            {
                lasttime = now;
                isdoing = false;
                return true;
            }

            return false;
        }

        private bool isdoing = false;
        private string lastsn = "";
        private int lastuid = 0;
        private void Starservice()
        {


            if (IsServerRunning)
            {   // 停止侦听
                if (TcpServer != null)
                {
                    TcpServer.Dispose();
                    
                }

                IsServerRunning = false;
                _logger.LogInformation("TCP停止侦听");
            }
            else
            {
                // 开启侦听
                TcpServer = new AsyncSocketAcceptor();
                TcpServer.FilterChain.AddLast("codec", new ProtocolCodecFilter(new FaceReaderProtocolCodecFactory(isEncryption, null)));

                TcpServer.SessionOpened += (o, ea) =>
                {
                    FaceReaderProtocolCodecFactory.EnablePassiveEncryption(ea.Session, true, SM2ServerInfo);
                };

                TcpServer.MessageReceived += async (o, ea) =>
                {

                  
                    // 显示接收字符串
                    string Message = (string)ea.Message;

                  //  _logger.LogInformation("TCP:" + Message);
                  
                    COMMAND_PCIR_TYPE A = Message.FromJsonTo<COMMAND_PCIR_TYPE>();
                    
                    if (string.Equals(A.COMMAND, "RecogniseResult"))
                    {

                        if (!String.IsNullOrEmpty( A.PARAM.score))
                        {
                            await SaveRecode(topath, A);
                        }


                        // 注意：保存数据然后进行回复
                        REPLY_PCIR_TYPE M = new REPLY_PCIR_TYPE();
                        M.RETURN = "RecogniseResult";
                        M.PARAM = new PARAM_REPLY_PCIR_TYPE();
                        M.PARAM.result = "success";
                        ea.Session.Write(M.ToJsonString());
                    }
                    else if (string.Equals(A.COMMAND, "Return"))
                    {
                         var ret = Message.FromJsonTo<ReturnResult>(); 
                        isdoing =false;
                        var facedowns = App.GetService<FacedownService>();
                        if (ret.PARAM.result.Equals("success"))
                        {
                            facedowns.Upstate(lastsn, lastuid);
                        }
                        else {
                            facedowns.Upstate(lastsn, lastuid, 0, ret.PARAM.reason);
                        }
                       
                    
                        SendUser(ea, lastsn);
                    }
                    else if (string.Equals(A.COMMAND, "GetRequest"))
                    {
                        SendUser(ea, A.PARAM.sn);
                        //if (string.IsNullOrEmpty(textBoxCommand.Text.Trim()))
                        //{
                        //    ea.Session.Close(true);
                        //}
                        //else
                        //{
                        //    ea.Session.Write(textBoxCommand.Text.Trim());
                        //}
                    }
                };

                TcpServer.ExceptionCaught += (o, ea) =>
                {   // 线程安全性

                    _logger.LogError(ea.Exception.Message.ToString());
                    ea.Session.Close(true);
                };

                // 绑定侦听端口，开始侦听
                TcpServer.Bind(new IPEndPoint(IPAddress.Parse(IP), port));

                IsServerRunning = true;

                _logger.LogInformation($"TCP开始侦听 : {port}");

            }
        }


        /// <summary>
        /// 保存刷脸记录
        /// </summary>
        /// <param name="path"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        private static async Task SaveRecode(string path, COMMAND_PCIR_TYPE rec)
        {
            //Console.WriteLine("打卡");
            var kqs = App.GetService<Kaoqin_logService>();
            var rdsconn = App.GetService<ConnectionMultiplexer>();


   
            //            logger.LogError();
            StringLoggingPart.Default().SetMessage($"{rec.PARAM.name}打卡 {rec.PARAM.sn}").LogInformation();
            Kaoqin_log kl = new Kaoqin_log();
            kl.cdate = DateTime.Now;
            kl.time = DateTime.Now; //Convert.ToDateTime(rec.info.time);
            kl.datep = kl.time.ToString("yyyy/MM/dd");
            kl.timep = kl.time.ToString("H:mm:ss");
            kl.authority = "facedoor2";
            kl.name = rec.PARAM.name;
            kl.Id = rec.PARAM.id;
            if (String.IsNullOrEmpty(kl.Id))
            {
                kl.Id = rec.PARAM.id.ToString();
            }
            kl.sn = rec.PARAM.sn;
            kl.scor = Convert.ToDecimal(rec.PARAM.score);
            var redis = rdsconn.GetDatabase(0);
            if (redis.KeyExists(kl.sn))
            {
                var db = App.GetService<ISqlSugarClient>();
                var adve = db.Queryable<Device>().Where(x => x.SN == kl.sn).First();
                redis.StringSet(kl.sn, adve.address, TimeSpan.FromMinutes(10));

            }
            try
            {
                kl.addr = redis.StringGet(kl.sn);
            }
            catch (Exception)
            {
                // StringLoggingPart.Default().SetMessage($"{kl.sn}地址获取错误").LogInformation();
                Console.WriteLine("地址获取错误");
            }

            if (kl.addr == null)
            {
                //  StringLoggingPart.Default().SetMessage($"{kl.sn}地址获取为空").LogInformation();
                kl.addr = "  ";
            }
            kl.wxtz = 0;
            kl.state = 0;
            kl.io = 0;
            kl.UID = "";




            try
            {
                String dir ="HW_"+ kl.time.ToString("yyMMdd");
                if (!Directory.Exists(path + dir))
                {
                    Directory.CreateDirectory(path + dir);
                }

                string imgPath = $"{kl.Id}_{DateTime.Now.Ticks}.jpg";


                OthTool.Base64StringToImage(rec.PARAM.capturejpg, $@"{path}{dir}/{imgPath}");

                kl.photo = $"{dir}/{imgPath}";
                Console.WriteLine("文件保存");
            }
            catch (Exception exr)
            {
                StringLoggingPart.Default().SetMessage($"文件保存失败：{exr.Message}").LogError();

            }

            await kqs.AddAsync(kl);
        }

        private void SendUser(IoSessionMessageEventArgs ea, string  sn)
        {
            if (isdoing)
            {
                if (!TimeOut())
                    return;
            }

            lastsn = sn;
            isdoing = true;

            var uses = App.GetService<UserService>();
            int i = 0;
            List<VUsers> lu = new List<VUsers>();
            int size = 1;
            var hasadd = true;
            int ernum = 0;
          
                lu = uses.Getall(sn, size, i);

                foreach (var item in lu)
                {
                    var M = new REPLY_GetRequest_TYPE();
                    M.RETURN = "GetRequest";
                    M.PARAM = new();
                    M.PARAM.name = item.username;
                    M.PARAM.id = item.user_id;
                    M.PARAM.job_num = item.user_id.ToString();
                    //  M.PARAM.throughStartTime= DateTime.Now.ToString("yyyy/MM/dd");
                    // M.PARAM.throughFinishTime = DateTime.Now.AddYears(9).ToString("yyyy/MM/dd");
                    M.PARAM.capturejpg = OthTool.ToBase64String(frompath + item.face);
                    M.PARAM.result = "success";
                    lastuid = M.PARAM.id;
                    String json = M.ToJsonString();
                    Console.WriteLine("Send:" + JsonConvert.SerializeObject(item));
                    ea.Session.Write(json);

                }
            if (lu.Count == 0)
            {
                size = 500;
                List<Users_del> del_user= new();
                do
                {

                    // 添加发送发完成 发送删除的用户
                     del_user = uses.GetDel(sn, size, i);
                    foreach (var item in del_user)
                    {
                        dynamic c = new Clay();
                        c.RETURN = "GetRequest";
                        c.PARAM = new
                        {
                            result = "success",
                            reason = "",
                            command = "DeleteEmployee",
                            id = item.user_id

                        };

                        Console.WriteLine("del Send:" + c.ToString());
                        ea.Session.Write(c.ToString());
                    }
                    i++;
                }while (del_user.Count==size);
            }


        }
    }
}
